<template lang="pug">
  el-form-item(:class="config.label?'':'form-label-hidden'" :label="config.label" :rules="rules")
    tree-select.tree-select(:required="required" :disabled="readonly" @input="change" v-model="value" :valueFormat="config.returnObject?'object':'id'" :async="config.loadType === 'async'&&config.connectType==='interface'?true:false" :load-options="debounceRemoteMethod" :value-consists-of="valueConsistsOf" :normalizer="normalizer" :placeholder="readonly?' ':config.placeholder" :multiple="config.selectType === 'multiple'" :options="options"
    :defaultOptions="config.loadType === 'async'&&config.connectType==='interface'?true:false" @open="menuOpen" @close="menuClose"  noOptionsText="无数据" noResultsText="无匹配数据" noChildrenText="无子节点" :appendToBody="true" :z-index="9999999999999")
</template>
<script>
import _ from 'lodash'
import inputCommon from '../../../../mixin/inputCommon'
import { invokeInterface } from '../../../../service'
import * as api from '../../../../service'
import treeSelect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {
  name: 'render',
  components: { treeSelect },
  props: ['config', 'editor'],
  inject: ['rootForm'],
  mixins: [inputCommon],
  data() {
    return {
      defaultFlag: false,
      options: [],
      valueConsistsOf: 'ALL', // 选中所有子节点 则展示所有选中的 BRANCH_PRIORITY LEAF_PRIORITY ALL_WITH_INDETERMINATE

      loading: false,
      cachedOptions: [],
      overLimitState: false, // 查询条数的提示语
      debounceRemoteMethod: _.debounce(this.remoteMethod, 300),

      // default: this.config.selectType === 'single' ? undefined : [],
      value: this.config.selectType === 'single' ? null : [],
      effectiveValue: ''
    }
  },
  methods: {
    dealTreeOptions() {
      if (!this.config.isTreeSelect) {
        _.forEach(this.options, one => {
          if (one.children) {
            one.children = JSON.stringify(one.children)
          }
        })
      }
    },
    change() {
      this.$refs.formItem && this.$refs.formItem.$emit('el.form.change', this.rootForm.properties[this.config.propertyName])
      return this.config.changeCb && this.getParsedFn('changeCb')()
    },
    normalizer(node) {
      let idKey = this.config.optionsValueKey
      let labelKey = this.config.optionsLabelKey
      let childrenKey = 'children'
      return {
        id: node[idKey] || node[labelKey],
        label: node[labelKey],
        children: node[childrenKey]
      }
    },
    remoteMethod({ action, searchQuery, callback }) {
      if (action === 'ASYNC_SEARCH') {
        // 异步初始值
        if (this.defaultFlag) {
          this.options = []
          let propertyNameVal = this.getValue()
          if (propertyNameVal) {
            if (this.config.returnObject) {
              if (_.isArray(propertyNameVal)) {
                this.options = propertyNameVal
              } else {
                this.options = [propertyNameVal]
              }
              this.dealTreeOptions()
              callback(null, this.options)
            } else {
              let searchQuery
              if (_.isArray(propertyNameVal)) {
                searchQuery = propertyNameVal
              } else {
                searchQuery = [propertyNameVal]
              }
              let searchQueryArr = _.map(searchQuery, one => {
                if (one) {
                  return this.getOptions(one)
                }
              })
              Promise.all(searchQueryArr).then(data => {
                _.forEach(data, one => {
                  this.options = _.uniqWith(one.concat(this.options), _.isEqual)
                })

                callback(null, this.options)
              })
            }
          }
          this.defaultFlag = false
        } else {
          this.getCachedOptions()
          this.getOptions(searchQuery).then(data => {
            if (this.config.selectType === 'multiple') {
              this.options = _.uniqWith(data.concat(this.cachedOptions), _.isEqual)
            } else {
              this.options = data
            }
            callback(null, this.options)
          })
        }
      }
    },
    // 聚焦事件
    menuOpen() {
      return this.config.focusCb && this.getParsedFn('focusCb')()
    },
    // 失去焦点事件
    menuClose() {
      return this.config.blurCb && this.getParsedFn('blurCb')()
    },
    getValue() {
      if (this.scope) {
        return this.scope[this.config.propertyName]
      } else {
        return this.rootForm.properties[this.config.propertyName]
      }
    },
    getCachedOptions() {
      let val = this.getValue()
      this.cachedOptions = []
      if (val) {
        if (this.config.returnObject) {
          if (_.isArray(val)) {
            this.cachedOptions = val
          } else {
            this.cachedOptions = [val]
          }
        } else {
          if (_.isArray(val)) {
            _.forEach(this.options, one => {
              if (val.indexOf(one[this.config.optionsValueKey]) > -1) {
                this.cachedOptions.push(one)
              }
            })
          } else {
            _.forEach(this.options, one => {
              if (val === one[this.config.optionsValueKey]) {
                this.cachedOptions.push(one)
              }
            })
          }
        }
      }
    },
    getOptions(query) {
      this.loading = true
      let setLimit = (params) => {
        if (!this.config.queryLimit) {
          this.config.queryLimit = 300
        }
        params.__limit = parseInt(this.config.queryLimit) + 1
      }
      let linkSearchExFn = this.getParsedEx('linkSearchEx')
      let params = { [this.config.queryKey]: query }
      if (this.config.linkSearch) {
        let v = linkSearchExFn()
        if (v !== 0) {
          v = v || ''
        }
        params[this.config.linkSearchQueryKey] = v
      }
      setLimit(params)
      return invokeInterface(this.config.dataInterfaceId, params).then((data) => {
        if (data.length > this.config.queryLimit) {
          data.pop()
          this.overLimitState = true
        } else {
          this.overLimitState = false
        }
        this.loading = false
        return data
      })
    },
    commit() {
      this.effectiveValue = this.value
    }
  },
  created() {
    // 关联值变化了  初始化数据刷新
    if (this.config.connectType === 'interface' && this.config.linkSearch) {
      this.$watch(this.getParsedEx('linkSearchEx'), (newValue) => {
        this.rootForm.properties[this.config.propertyName] = this.default
        this.getOptions().then(data => {
          this.options = data
        })
      })
    }
    // this.options = [{ label: '苹果', value: 'apple' }, { label: '香蕉', value: 'banner' }, {
    //   label: '橘子',
    //   value: 'orange'
    // }, { label: '水果', value: 'fruit' }]
    // 是否为(接口)搜索还是直接（字典）
    // 是否为(接口)搜索还是直接（字典）
    if (this.config.connectType === 'dictionary' && this.config.dataDictionaryId) {
      this.options = []
      // 当返回对象且直接加载时，页面显示的信息会等获取数据接口成功才回显，并不会直接拿对象里的数据
      if (this.config.returnObject && this.config.selectType === 'single' && this.getValue()) {
        this.options = [this.getValue()]
      } else if (this.config.returnObject && this.config.selectType === 'multiple' && this.getValue() && this.getValue().length > 0) {
        this.options = this.getValue()
      }
      this.dealTreeOptions()

      this.config.optionsValueKey = 'value'
      this.config.optionsLabelKey = 'label'
      api.getDictionaryData(this.config.dataDictionaryId).then(data => {
        this.options = _.cloneDeep(data)
        this.dealTreeOptions()
      })
    } else if (this.config.connectType === 'interface') {
      if (window.sessionStorage.formConfig) {
        let oldConfig = JSON.parse(window.sessionStorage.formConfig)

        if (oldConfig.dataInterfaceId === this.config.dataInterfaceId && this.config.searchClick === oldConfig.searchClick) {
          return
        }else{
          window.sessionStorage.setItem('formConfig', JSON.stringify(this.config))
        }
      }else{
        window.sessionStorage.setItem('formConfig', JSON.stringify(this.config))
      }
      this.options = []
      // 当返回对象且直接加载时，页面显示的信息会等获取数据接口成功才回显，并不会直接拿对象里的数据
      if (this.config.returnObject && this.config.selectType === 'single' && this.getValue()) {
        this.options = [this.getValue()]
      } else if (this.config.returnObject && this.config.selectType === 'multiple' && this.getValue() && this.getValue().length > 0) {
        this.options = this.getValue()
      }
      this.dealTreeOptions()
      if (this.config.dataInterfaceId) {
        if (this.config.loadType === 'async') {
          // 远程搜索
          this.defaultFlag = true
        } else {
          this.getOptions().then(data => {
            this.options = data
            this.dealTreeOptions()
          })
        }
      }
    }

    this.observer = this.rootForm.dataInterfaceObserverManage.get(this.config.filterdataInterfaceId)
    if (this.config.type === 'param') {
      this.paramsGetter = () => {
        let obj = {}
        let params = this.config.paramName.split(',')
        params.forEach(one => {
          obj[one] = this.effectiveValue
        })
        return obj
      }
      this.observer.addParamsGetter(this.paramsGetter)
    } else if (this.config.type === 'normal') {
      let filter = (data, filterKeyList) => {
        return data.filter(one => filterKeyList.some(key => {
          let v = _.at(one, key)[0]
          if (!v) {
            return false
          }
          let effectiveValue = this.config.selectType === 'single' ? this.effectiveValue : JSON.stringify(this.effectiveValue)
          return v.indexOf(effectiveValue) > -1
        }))
      }

      this.filterFn = (data) => {
        let filterKeyList = this.config.filterKeys.split(',').map(one => one.trim())
        if (this.config.listKey) {
          let list = _.at(data, this.config.listKey)[0]
          let filteredList = filter(list, filterKeyList)
          _.update(data, this.config.listKey, () => filteredList)
          return data
        }
        return filter(data, filterKeyList)
      }
      this.observer.addFilter(this.filterFn)
    }
  },
  beforeDestroy() {
    if (this.config.type === 'param') {
      this.observer.removeParamsGetter(this.paramsGetter)
    } else if (this.config.type === 'normal') {
      this.observer.removeFilter(this.filterFn)
    }
  }
}
</script>
